package open.template.work.gateway.filter;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import open.template.work.commons.encrypt.Md5Sign;
import open.template.work.commons.exception.BaseTemplateException;
import open.template.work.commons.exception.ExceptionCodeEnum;
import open.template.work.commons.http.HttpParser;
import open.template.work.gateway.service.AuthorizationService;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.Map;
import java.util.Set;

@Component
public class AuthorizationFilter extends ZuulFilter {

    private Logger LOGGER = LoggerFactory.getLogger(getClass());

    @Autowired
    AuthorizationService authorizationService;

    @Override
    public String filterType() {
        // 在进行Zuul过滤的时候可以设置其过滤执行的位置，那么此时有如下几种类型：
        // 1、pre：在请求发出之前执行过滤，如果要进行访问，肯定在请求前设置头信息
        // 2、route：在进行路由请求的时候被调用；
        // 3、post：在路由之后发送请求信息的时候被调用；
        // 4、error：出现错误之后进行调用
        return "pre";
    }

    @Override
    public int filterOrder() {
        // 设置优先级，数字越大优先级越低
        return 0;
    }

    @Override
    public boolean shouldFilter() {
        // 该Filter是否要执行
        return true;
    }

    @Override
    public Object run() {
        RequestContext currentContext = RequestContext.getCurrentContext(); // 获取当前请求的上下文
        Map<String, Object> params = null;
        try {
            //1.获取请求参数，支持json格式数据，通过inputstream解析数据
            try {
                params = HttpParser.requestJsonParser(currentContext.getRequest().getInputStream());

            } catch (Exception e) {
                throw new BaseTemplateException(ExceptionCodeEnum.Z88888);
            }

            LOGGER.info("获取授权参数data={}", params);

            //2.通过md5验签，生产环境可以根据需求调整更复杂的算法，为了测试简单暂时通过客户端的treemap进行排序，将所有参数生成字符串，然后拼接用户密钥
            //生成md5作为签名
            if (params.get("appKey") != null) {
                String key = authorizationService.getUserKey(params.get("appKey").toString());
                if (StringUtils.isEmpty(key)) {
                    throw new BaseTemplateException(ExceptionCodeEnum.Z88887);
                }

                Object sign = params.get("sign");
                if (sign == null) {
                    throw new BaseTemplateException(ExceptionCodeEnum.Z88888);
                }

                StringBuffer stringBuffer = new StringBuffer();
                Set<String> paramsSet = params.keySet();
                for (String param : paramsSet) {
                    if (!param.equals("sign")) {
                        stringBuffer.append(params.get(param));
                    }
                }
                //本地加签
                String localSign = Md5Sign.sign(stringBuffer.append(key).toString());
                if (!localSign.equals(sign)) {
                    throw new BaseTemplateException(ExceptionCodeEnum.Z88888);
                }

            }
        } catch (BaseTemplateException e) {
            currentContext.setSendZuulResponse(false);
            currentContext.setResponseStatusCode(200);
            currentContext.setResponseBody("{\"result \":\""+e.getMessage()+"\"}");
            currentContext.getResponse().setContentType("text/html;charset=UTF-8");
        }

        return null;

    }


}
